use std::future::Future;
use std::pin::Pin;
use tokio::task::JoinHandle;

pub trait Dispatcher: Send + Sync {
    fn schedule_fn<'a>(&'a self, f: Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> + Send + 'a>) -> JoinHandle<()>;
}

pub struct ThreadPoolDispatcher {
    pool: tokio::runtime::Handle,
}

impl ThreadPoolDispatcher {
    pub fn new(threads: usize) -> Self {
        let runtime = tokio::runtime::Builder::new_multi_thread()
            .worker_threads(threads)
            .build()
            .unwrap();
        Self {
            pool: runtime.handle().clone(),
        }
    }
}

impl Dispatcher for ThreadPoolDispatcher {
    fn schedule_fn<'a>(&'a self, f: Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> + Send + 'a>) -> JoinHandle<()> {
        self.pool.spawn(async move {
            f().await;
        })
    }
}

pub struct CurrentThreadDispatcher;

impl CurrentThreadDispatcher {
    pub fn new() -> Self {
        Self
    }
}

impl Dispatcher for CurrentThreadDispatcher {
    fn schedule_fn<'a>(&'a self, f: Box<dyn FnOnce() -> Pin<Box<dyn Future<Output = ()> + Send + 'a>> + Send + 'a>) -> JoinHandle<()> {
        tokio::task::spawn(async move {
            f().await;
        })
    }
} 